package nl.boektrust.btsoep.server.wsdl;

import java.util.Iterator;
import javax.xml.bind.JAXB;
import javax.xml.namespace.QName;
import javax.xml.soap.MessageFactory;
import javax.xml.soap.SAAJResult;
import javax.xml.soap.SOAPBody;
import javax.xml.soap.SOAPElement;
import javax.xml.soap.SOAPException;
import javax.xml.soap.SOAPFault;
import javax.xml.soap.SOAPMessage;
import javax.xml.transform.dom.DOMSource;
import nl.boektrust.btsoep.server.wsdl.jaxws.SearchBooks;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class BrowseSoapHandler {
	private static final Logger logger = LoggerFactory
			.getLogger(BrowseSoapHandler.class);
	private final BrowseAdapter browseAdapter;

	public BrowseSoapHandler()
			throws SOAPException {
		browseAdapter = new BrowseAdapter();
	}

	public static QName getQName(Class<?> clz) {
		String name = clz
				.getAnnotation(javax.xml.bind.annotation.XmlType.class).name();
		String namespace = clz.getAnnotation(
				javax.xml.bind.annotation.XmlType.class).namespace();
		QName qn = new QName(namespace, name);
		return qn;
	}

	/**
	 * handleSOAPRequest.
	 * @param request Will be changed.
	 * @return
	 * @throws SOAPException
	 */
	public SOAPMessage handleSOAPRequest(SOAPMessage request)
			throws SOAPException {
		QName searchBooksQName = getQName(SearchBooks.class);
		SOAPBody soapBody = request.getSOAPBody();
		Iterator iterator = soapBody.getChildElements();
		Object responsePojo = null;
		while (iterator.hasNext()) {
			Object next = iterator.next();
			if (next instanceof SOAPElement) {
				SOAPElement soapElement = (SOAPElement) next;
				QName qname = soapElement.getElementQName();
				if (searchBooksQName.equals(qname)) {
					SearchBooks searchBooks = JAXB.unmarshal(new DOMSource(
							soapElement), SearchBooks.class);
					responsePojo = browseAdapter.searchBooks(searchBooks);
					break;
				}
			}
		}
		// messageFactory.createMessage(); does throw new
		// UnsupportedOperationException(); so I reuse request
		SOAPMessage soapMessage = request;
		soapBody = soapMessage.getSOAPBody();
		if (responsePojo != null) {
			JAXB.marshal(responsePojo, new SAAJResult(soapBody));
		} else {
			SOAPFault fault = soapBody.addFault();
			fault.setFaultString("Unrecognized SOAP request.");
		}
		return soapMessage;
	}

}
